use model_graph_types::{
    container::workflow::{
        ListOperatorStatement, WorkflowBlockExecuteResult, WorkflowBlockExecuteResultBuilder,
        WorkflowBlockExecuteResultStatus,
    },
    modeling::{ComparsionOperator, Value},
};
use std::{
    collections::HashMap,
    sync::{Arc, Mutex},
};

use crate::workflow::context::{Getter, WorkflowContext};

pub async fn execute(
    statement: &ListOperatorStatement,
    context: Arc<Mutex<WorkflowContext>>,
) -> anyhow::Result<WorkflowBlockExecuteResult> {
    let result = _execute(statement, context).await;

    match result {
        Ok(v) => Ok(WorkflowBlockExecuteResultBuilder::default()
            .status(WorkflowBlockExecuteResultStatus::Succeeded)
            .source_handle("source")
            .result(v)
            .build()?),
        Err(err) => Ok(WorkflowBlockExecuteResultBuilder::default()
            .status(WorkflowBlockExecuteResultStatus::Succeeded)
            .source_handle("fail-branch")
            .build()?),
    }
}

pub async fn _execute(
    statement: &ListOperatorStatement,
    context: Arc<Mutex<WorkflowContext>>,
) -> anyhow::Result<HashMap<String, Value>> {
    //
    let variable = &statement.variable;
    let filter_by = &statement.filter_by;
    let extract_by = &statement.extract_by;
    let order_by = &statement.order_by;
    let limit = &statement.limit;
    let var_type = &statement.var_type;
    let item_var_type = &statement.item_var_type;

    //获取到变量
    let iterator_value = context.get_from_node(&variable.1, &variable.0)?;

    let mut values = match iterator_value {
        Value::Array(v) => v,
        _ => vec![iterator_value],
    };
    tracing::error!("{:?}", values);
    //filter
    if filter_by.enabled {
        for condition in &filter_by.conditions {
            values.retain(|x| match &condition.comparsion_operator {
                ComparsionOperator::StartWith => x.starts_with(&condition.value),
                ComparsionOperator::Contains => x.contains(&condition.value),
                ComparsionOperator::NotContains => !x.contains(&condition.value),
                ComparsionOperator::EndWith => x.ends_with(&condition.value),
                ComparsionOperator::NotEmpty => !x.is_empty(),
                ComparsionOperator::Empty => x.is_empty(),
                _ => false,
            });
        }
    }
    tracing::error!("{:?}", values);
    //limit
    if limit.enabled {
        if let Some(size) = limit.size {
            values.resize(size.try_into()?, Value::None);
        }
    }
    let mut result: HashMap<String, Value> = HashMap::new();

    result.insert(String::from("result"), Value::Array(values));
    //
    Ok(result)
}
